//
//  ImageProcessingAlgorithmInvoker.m
//  IphoneImageProcessing
//
//  Created by Ngoc on 5/2/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "ImageProcessingAlgorithmInvoker.h"


@implementation ImageProcessingAlgorithmInvoker

-(void) Execute:(id<ICommand>)command 
{
    // prepare for undo.
    if(nil == undoStack) 
        undoStack = [[NSMutableArray alloc] initWithCapacity:maxUndolevels];
    else if([undoStack count] == maxUndolevels)
    {
        [undoStack removeObject:0];
    }
    
    [command Execute];
    [undoStack addObject:command];
    // If can redo but user stop undo and excute other action then we delete redoStack
    if([self IsCanRedo] && ![redoStack containsObject:command])
        [redoStack removeAllObjects];
}

-(void) Undo:(NSInteger)levels
{
    NSInteger count =levels;
    @try {
        
        while (count-- >0 && [self IsCanUndo]) {
            id<ICommand> command = [undoStack objectAtIndex:[undoStack count]-1];
            if(command) 
            {
                [command Undo];
                // prepare for redo
                if(nil==redoStack) 
                    redoStack = [[NSMutableArray alloc]initWithCapacity:maxUndolevels];
                else if([redoStack count]== maxUndolevels)
                    [redoStack removeObject:0];
                
                [redoStack addObject:command];
            }
            [command release];
            
        }
        
    }
    @catch (NSException *exception) {
        @throw exception;
    }
    
}
-(void) Redo:(NSInteger)levels
{
    NSInteger count = levels;
    @try {
        
        while(count-- >0 && [self IsCanRedo])
        {
            id<ICommand> command = (id<ICommand>)[redoStack objectAtIndex:[redoStack count]-1];
            if(command) 
            {
                [self Execute:command];
                [redoStack removeObject:command];
            }
        }
    }
    @catch (NSException *exception) {
        @throw exception;
    }
    
}
-(BOOL) IsCanUndo
{
    BOOL cant = NO;
    if (undoStack && [undoStack count]>0)
    {
        cant = YES;
    }
    return cant;
}
-(BOOL) IsCanRedo
{
    BOOL cant = NO;
    if (redoStack && [redoStack count]>0)
    {
        cant = YES;
    }
    return cant;
}
@end
